package org.akomantoso.core.data;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.akomantoso.core.data.attribute.Alt;
import org.akomantoso.core.data.attribute.CoreOpt;
import org.akomantoso.core.data.attribute.Enactment;
import org.akomantoso.core.data.attribute.HTMLattrs;
import org.akomantoso.core.data.attribute.IdOpt;
import org.akomantoso.core.data.attribute.Refers;
import org.akomantoso.core.data.attribute.SpeechAtts;
import org.akomantoso.core.data.attribute.XmlLang;
import org.akomantoso.core.data.group.BlockElements;
import org.akomantoso.core.data.type.StatusType;
import org.akomantoso.core.io.Input;
import org.akomantoso.core.io.Output;
import org.akomantoso.core.io.OutputUtil;
import org.akomantoso.core.io.util.group.BlockElementsGroup;

/**
 * the complex type speechType defines the content model and attributes shared by all speech elements. Here the id
 * attribute is optional.
 * 
 * <pre>
 * <xsd:complexType name="speechType">
 * 		<xsd:complexContent>
 * 			<xsd:extension base="basehierarchy">
 * 				<xsd:sequence>
 * 					<xsd:element ref="from" minOccurs="0" maxOccurs="1"/>
 * 					<xsd:sequence minOccurs="1" maxOccurs="unbounded">
 * 						<xsd:group ref="blockElements"/>
 * 					</xsd:sequence>
 * 				</xsd:sequence>
 * 				<xsd:attributeGroup ref="coreopt"/>
 * 				<xsd:attributeGroup ref="speechAtts"/>
 * 		</xsd:extension>
 * 		</xsd:complexContent>
 * </xsd:complexType>
 * </pre>
 * 
 * @author <a href="mailto:jacques.militello@gmail.com">Jacques Militello</a>
 * 
 * @since http://www.akomantoso.org/1.0
 * 
 */
public abstract class SpeechType extends BaseHierarchy implements CoreOpt, SpeechAtts {

	// from HTMLattrs
	private String _class;
	private String _style;
	private String _title;

	// from Enactment
	private StatusType _status;
	private String _period;

	// from IdOpt
	private String _id;
	private String _evolvingId;

	// from Refers
	private String _refersTo;

	// from XmlLang
	private String _xmlLang;

	// Alt
	private String _alternativeTo;

	private String _by;
	private String _as;
	private String _to;

	private From _from;

	private final List<BlockElements> _blockElements = new ArrayList<BlockElements>(4);

	/**
	 * @see org.akomantoso.core.data.attribute.HTMLattrs#getClazz()
	 */
	public String getClazz() {
		return _class;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.HTMLattrs#setClazz(java.lang.String)
	 */
	public void setClazz(String clazz) {
		_class = clazz;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.HTMLattrs#getStyle()
	 */
	public String getStyle() {
		return _style;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.HTMLattrs#setStyle(java.lang.String)
	 */
	public void setStyle(String style) {
		_style = style;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.HTMLattrs#getTitle()
	 */
	public String getTitle() {
		return _title;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.HTMLattrs#setTitle(java.lang.String)
	 */
	public void setTitle(String title) {
		_title = title;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.Enactment#getStatus()
	 */
	public StatusType getStatus() {
		return _status;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.Enactment#setStatus(org.akomantoso.core.data.type.StatusType)
	 */
	public void setStatus(StatusType status) {
		_status = status;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.Enactment#getPeriod()
	 */
	public String getPeriod() {
		return _period;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.Enactment#setPeriod(java.lang.String)
	 */
	public void setPeriod(String period) {
		_period = period;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.IdOpt#getId()
	 */
	public String getId() {
		return _id;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.IdOpt#setId(java.lang.String)
	 */
	public void setId(String id) {
		_id = id;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.IdOpt#getEvolvingId()
	 */
	public String getEvolvingId() {
		return _evolvingId;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.IdOpt#setEvolvingId(java.lang.String)
	 */
	public void setEvolvingId(String evolvingId) {
		_evolvingId = evolvingId;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.Refers#getRefersTo()
	 */
	public String getRefersTo() {
		return _refersTo;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.Refers#setRefersTo(java.lang.String)
	 */
	public void setRefersTo(String refersTo) {
		_refersTo = refersTo;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.XmlLang#getXmlLang()
	 */
	public String getXmlLang() {
		return _xmlLang;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.XmlLang#setXmlLang(java.lang.String)
	 */
	public void setXmlLang(String xmlLang) {
		_xmlLang = xmlLang;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.Alt#getAlternativeTo()
	 */
	public String getAlternativeTo() {
		return _alternativeTo;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.Alt#setAlternativeTo(java.lang.String)
	 */
	public void setAlternativeTo(String alternativeTo) {
		_alternativeTo = alternativeTo;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.SpeechAtts#getBy()
	 */
	public String getBy() {
		return _by;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.SpeechAtts#setBy(java.lang.String)
	 */
	public void setBy(String by) {
		_by = by;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.SpeechAtts#getAs()
	 */
	public String getAs() {
		return _as;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.SpeechAtts#setAs(java.lang.String)
	 */
	public void setAs(String as) {
		_as = as;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.SpeechAtts#getTo()
	 */
	public String getTo() {
		return _to;
	}

	/**
	 * @see org.akomantoso.core.data.attribute.SpeechAtts#setTo(java.lang.String)
	 */
	public void setTo(String to) {
		_to = to;
	}

	public From getFrom() {
		return _from;
	}

	public void setFrom(From from) {
		_from = from;
	}

	public List<BlockElements> getBlockElements() {
		return _blockElements;
	}

	public void addBlockElement(BlockElements blockElement) {
		_blockElements.add(blockElement);
	}

	/**
	 * @see org.akomantoso.core.data.BaseHierarchy#writeExternal(org.akomantoso.core.io.Output)
	 */
	@Override
	public <T extends Output> void writeExternal(T out) throws IOException {
		// from idOpt
		OutputUtil.writeIdOpt(out, this);
		// from XmlLang
		OutputUtil.writeAttribute(out, XmlLang.PREFIX_AND_ATTRIBUTE, _xmlLang);
		// from HTMLattrs
		OutputUtil.writeHTMLattrs(out, this);
		// from Enactment
		OutputUtil.writeEnactment(out, this);
		// from Refers
		OutputUtil.writeRefers(out, this);
		// from Alt
		OutputUtil.writeAttribute(out, Alt.ATTRIBUTE, _alternativeTo);

		OutputUtil.writeSpeechAtts(out, this);
		super.writeExternal(out);
		if (_from != null) {
			_from.writeExternal(out);
		}
		for (int i = 0, n = _blockElements.size(); i < n; i++) {
			_blockElements.get(i).writeExternal(out);
		}
	}

	/**
	 * @see org.akomantoso.core.data.BaseHierarchy#readExternal(org.akomantoso.core.io.Input)
	 */
	@Override
	public <T extends Input> void readExternal(T in) throws IOException {
		
		final String localName = in.getLocalName();
		
		// from idOpt
		_id = in.readAttribute(IdOpt.ATTRIBUTE_ID);
		_evolvingId = in.readAttribute(IdOpt.ATTRIBUTE_EVOLVING_ID);
		// from XmlLang
		_xmlLang = in.readAttribute(XmlLang.NAMESPACE_URI,XmlLang.ATTRIBUTE);

		// from Enactment
		String temp = in.readAttribute(Enactment.ATTRIBUTE_STATUS);
		if (temp != null) {
			_status = StatusType.valueOf(temp);
		}
		_period = in.readAttribute(Enactment.ATTRIBUTE);

		// from HTMLattrs
		_class = in.readAttribute(HTMLattrs.ATTRIBUT_CLASS);
		_style = in.readAttribute(HTMLattrs.ATTRIBUT_STYLE);
		_title = in.readAttribute(HTMLattrs.ATTRIBUT_TITLE);

		// from Refers
		_refersTo = in.readAttribute(Refers.ATTRIBUTE);

		// from Alt
		_alternativeTo = in.readAttribute(Alt.ATTRIBUTE);
		
		_by = in.readAttribute(SpeechAtts.ATTRIBUTE_BY);
		_as = in.readAttribute(SpeechAtts.ATTRIBUTE_AS);
		_to = in.readAttribute(SpeechAtts.ATTRIBUTE_TO);
		
		super.readExternal(in);
		
		if (From.ELEMENT == in.getLocalName()) {
			_from = new From();
			_from.readExternal(in);
			in.readNextStartOrEndElement();
		}

		BlockElementsGroup.read(in, _blockElements, localName);
		
	}

}